package com.colin.videoservice.service.impl;

import cn.dev33.satoken.stp.StpUtil;
import cn.hutool.core.lang.Snowflake;
import com.aliyun.oss.OSS;
import com.aliyun.oss.model.PutObjectRequest;
import com.colin.bean.Video;
import com.colin.bean.VideoCollect;
import com.colin.bean.VideoLike;
import com.colin.response.R;
import com.colin.response.RCM;
import com.colin.videoservice.exception.sub.VideoNotExistException;
import com.colin.videoservice.mapper.VideoMapper;
import com.colin.videoservice.service.VideoService;
import com.colin.videoservice.util.VideoUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;
import java.time.LocalDateTime;
import java.util.List;

@Slf4j
@Service
public class VideoServiceImpl implements VideoService {

    @Value("${aliyun.oss.bucket-name}")
    private String bucketName;

    @Value("${aliyun.oss.endpoint}")
    private String endpoint;

    @Autowired
    private RabbitTemplate rabbitTemplate;

    @Autowired
    private VideoMapper videoMapper;

    @Autowired
    private Snowflake snowflake;

    @Autowired
    private OSS ossClient;

    /**
     * 获取视频信息
     * @param videoId
     * @return
     */
    @Override
    public R<Video> getVideoPath(Long videoId) {
        //从数据库获取视频信息以及存储在OSS中的文件路径
        Video video = videoMapper.selectById(videoId);
        if (video == null) {
            throw new VideoNotExistException(RCM.VIDEO_NOT_EXIST.getMessage());
        }
        return R.ok(video);
    }

    /**
     * 删除视频
     * @param videoId
     * @return
     */
    @Override
    public R<Boolean> deleteVideo(Long videoId) {
        String loginId = (String) StpUtil.getLoginId();
        //检测是否是登录用户发布的视频
        if (videoMapper.checkPublish(loginId,videoId)==null) {
            log.error("非该登录用户发布的视频 无法删除 用户id：{}",loginId);
            throw new VideoNotExistException(RCM.VIDEO_NOT_CONFORM_TO_USER.getMessage());
        }
        if (!videoMapper.deleteById(videoId)) {
            throw new VideoNotExistException(RCM.VIDEO_NOT_EXIST.getMessage());
        }
        return R.ok(true);
    }

    /**
     * 对视频进行点赞
     * @param videoId
     * @return
     */
    @Override
    public R<Boolean> likeVideo(String videoId) {
        //检测视频是否存在
        if (videoMapper.isExistVideo(videoId)==null) {
            throw new VideoNotExistException(RCM.VIDEO_NOT_EXIST.getMessage());
        }
        String loginId = (String) StpUtil.getLoginId();
        //检测视频是否已经添加到了点赞表中，如果添加了修改状态即可
        if (videoMapper.checkLikeVideo(loginId, videoId) != null) {
            return R.ok(videoMapper.updateLikeVideo(videoId, loginId, LocalDateTime.now()));
        }
        videoMapper.likeVideo(videoId, loginId, LocalDateTime.now());
        //点赞数增加
        videoMapper.addLikeCount(videoId);
        return R.ok(true);
    }

    /**
     * 收藏视频
     * @param videoId
     * @return
     */
    @Override
    @Transactional
    public R<Boolean> collectVideo(String videoId) {
        //检测视频是否存在
        if (videoMapper.isExistVideo(videoId)==null) {
            throw new VideoNotExistException(RCM.VIDEO_NOT_EXIST.getMessage());
        }
        String loginId = (String) StpUtil.getLoginId();
        //检测视频是否在收藏表中，如果在，修改状态
        if (videoMapper.checkCollectVideo(loginId, videoId) != null) {
            return R.ok(videoMapper.updateCollectVideo(videoId, loginId, LocalDateTime.now()));
        }
        videoMapper.collectVideo(videoId,loginId,LocalDateTime.now());
        //收藏数增加
        videoMapper.addCollectCount(videoId);
        return R.ok(true);
    }

    /**
     * 通过关键词搜索视频
     * @param keyword
     * @return
     */
    @Override
    public R<List<Video>> searchVideoList(String keyword) {
        System.out.println(keyword);
        List<Video> videoList = videoMapper.searchVideoByKeyword(keyword);
        if (videoList.isEmpty()) {
            throw new VideoNotExistException(RCM.VIDEO_NOT_EXIST.getMessage());
        }
        return R.ok(videoList);
    }


    /**
     * 给视频取消点赞
     * @param videoId
     * @return
     */
    @Override
    public R<Boolean> doDisLikeVideo(String videoId) {
        String loginId = (String) StpUtil.getLoginId();
        videoMapper.decreaseLikeCount(videoId);
        return R.ok(videoMapper.deleteLikeVideo(videoId ,loginId)) ;
    }

    /**
     * 获取视频点赞列表
     * @return
     */
    @Override
    public R<List<Video>> getLikeVideoList() {
        String loginId = (String) StpUtil.getLoginId();
        return R.ok(videoMapper.getLikeVideo(loginId));
    }

    /**
     * 获取视频收藏列表
     * @return
     */
    @Override
    public R<List<Video>> getCollectVideoList() {
        String loginId = (String) StpUtil.getLoginId();
        return R.ok(videoMapper.getCollectVideo(loginId)) ;
    }

    /**
     * 给视频取消收藏
     * @param videoId
     * @return
     */
    @Override
    public R<Boolean> doUnCollectVideo(String videoId) {
        String loginId = (String) StpUtil.getLoginId();
        videoMapper.decreaseCollectCount(videoId);
        return R.ok(videoMapper.deleteCollectVideo(videoId, loginId));
    }

    @Override
    public R<Boolean> initVideo() {
        String loginId = (String) StpUtil.getLoginId();
        if(videoMapper.isExistVideoInit(loginId)!=null) {
            return R.ok(true);
        }
        //通过雪花算法生成全局id
        long videoId = snowflake.nextId();
        log.info("雪花算法生成id：{}", videoId);
        rabbitTemplate.convertAndSend("video.ttl.queue",videoId);
        return R.ok(videoMapper.initVideo(loginId, videoId));
    }

    @Override
    public R<Boolean> uploadVideo(MultipartFile videoFile) {
        String loginId = (String) StpUtil.getLoginId();
        String videoObjectKey = VideoUtil.generateVideoObjectKey(videoFile.getOriginalFilename(), loginId , videoFile.getOriginalFilename());
        try {
            // 2. 验证文件类型
            VideoUtil.validateVideoFile(videoFile);
            PutObjectRequest putObjectRequest = new PutObjectRequest(bucketName, videoObjectKey, videoFile.getInputStream());

            ossClient.putObject(putObjectRequest);
            String cleanEndpoint = endpoint.replaceAll("^https?://", "");

            // 构建标准OSS外网访问域名格式
            String videoUrl = "https://" + bucketName + "." + cleanEndpoint + "/" + videoObjectKey;
            log.info("上传视频的url：{}",videoUrl);
            return R.ok(videoMapper.updateVideoUrl(videoUrl,loginId));
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

    @Override
    public R<Boolean> uploadCover(MultipartFile coverFile) {
        String loginId = (String) StpUtil.getLoginId();
        String coverObejectKet = VideoUtil.generateCoverObjectKey(coverFile.getOriginalFilename(), loginId );
        try {
            PutObjectRequest putObjectRequest = new PutObjectRequest(bucketName, coverObejectKet, coverFile.getInputStream());

            ossClient.putObject(putObjectRequest);
            String cleanEndpoint = endpoint.replaceAll("^https?://", "");

            // 构建标准OSS外网访问域名格式
            String coverUrl = "https://" + bucketName + "." + cleanEndpoint + "/" + coverObejectKet;
            log.info("上传视频的url：{}",coverUrl);
            return R.ok(videoMapper.updateCoverUrl(coverUrl,loginId));
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

    @Override
    public R<Boolean> uploadVideoDetail(Video videoDetail) {
        String loginId = (String) StpUtil.getLoginId();
        //封装基本的video属性
        videoDetail.setUserId(Long.valueOf(loginId));
        videoDetail.setDurationTime(Video.secondsToTimeFormat(Long.valueOf(videoDetail.getDurationSeconds())));
        videoDetail.setViews(0);
        videoDetail.setCollects(0);
        videoDetail.setCreateTime(LocalDateTime.now());
        videoDetail.setDanmakuCount(0);
        videoDetail.setLikes(0);
        videoDetail.setStatus(1);
        return R.ok(videoMapper.uploadVideoDetail(videoDetail));
    }

    @Override
    public R<VideoLike> getLikeStatus(String videoId) {
        String loginId = (String) StpUtil.getLoginId();
        return R.ok(videoMapper.getLikeStatus(videoId, loginId));
    }

    @Override
    public R<VideoCollect> getCollectStatus(String videoId) {
        String loginId = (String) StpUtil.getLoginId();
        return R.ok(videoMapper.getCollectStatus(videoId, loginId));
    }
}
